In [1]:
%pylab inline


Populating the interactive namespace from numpy and matplotlib

In [2]:
import config
from cpp_wrapper.tree_based_regression import AlignmentMethod

In [3]:
def computeErrorForAllLandmarks(alignment_method, bounding_boxes, images, ground_truth, eyes_index, landmarks_number):
    error = []
    
    for bounding_box, img, ground_truth in zip(bounding_boxes, images, ground_truth):
        interpupil_distance = np.linalg.norm(ground_truth[eyes_index[0]] - ground_truth[eyes_index[1]])
        shape = alignment_method.align(bounding_box, img)
        error.append(np.linalg.norm(shape - ground_truth, axis=1) / interpupil_distance)
        
    return np.array(error)


def computeError(alignment_method, bounding_boxes, images, ground_truth, eyes_index, landmarks_number):
    error = []
    
    for bounding_box, img, ground_truth in zip(bounding_boxes, images, ground_truth):
        interpupil_distance = np.linalg.norm(ground_truth[eyes_index[0]] - ground_truth[eyes_index[1]])
        shape = alignment_method.align(bounding_box, img)
        error.append(np.sum(np.linalg.norm(shape - ground_truth, axis=1) / interpupil_distance) / landmarks_number)
        
    return error

def ecdf(x, line_style="-", label=None):
    hist, bins_steps = histogram(x, bins=500)
    values = [(bins_steps[i]+bins_steps[i+1])/2 for i in range(bins_steps.shape[0]-1)]
    cumsum = np.cumsum(hist).astype(np.float)
    if label is not None:
        plot(values, cumsum/cumsum[-1], line_style, label=label)
    else:
        plot(values, cumsum/cumsum[-1], line_style)

300-W


In [4]:
from datasets import _300w

def compute300WError(alignment_method, bounding_boxes, images, ground_truth):
    return computeError(alignment_method, bounding_boxes, images, ground_truth, (36, 45), 68)

Node separation criteria


In [5]:
node_separation_criterias = ["ls", "var", "mean_norm", "normalized_ls", "normalized_var"]

labels = ["LS", "Min variances", "Max means' norms", "Normalized LS", "Min normalized variances"]

images, ground_truth, bounding_boxes = _300w.loadTestSet()
criterias_test_errors = []

for criteria in node_separation_criterias:
    local_trees_alignment = AlignmentMethod(os.path.join(config._300w_benchmark_path, "criterias", "local_trees_regression_model_300w_%s.txt" % criteria))
    criterias_test_errors.append(compute300WError(local_trees_alignment, bounding_boxes, images, ground_truth))

_ = boxplot([test_error for test_error in criterias_test_errors], sym="")



In [6]:
node_separation_criterias = ["ls", "var", "mean_norm", "normalized_ls", "normalized_var"]

labels = ["LS", "Min variances", "Max means' norms", "Normalized LS", "Min normalized variances"]

images, ground_truth, bounding_boxes = _300w.loadTestSet()
criterias_test_errors = []

for criteria in node_separation_criterias:
    lbf_alignment = AlignmentMethod(os.path.join(config._300w_benchmark_path, "criterias", "lbf_regression_model_300w_%s.txt" % criteria), method="lbf")
    criterias_test_errors.append(compute300WError(lbf_alignment, bounding_boxes, images, ground_truth))

_ = boxplot([test_error for test_error in criterias_test_errors], sym="")


68 landmarks testing


In [7]:
images, ground_truth, bounding_boxes = _300w.loadTestSet()

test_errors = []
labels = []

local_trees_alignment = AlignmentMethod(os.path.join(config._300w_benchmark_path, "local_trees_regression_model_300w_68_landmarks.txt"))
lbf_alignment = AlignmentMethod(os.path.join(config._300w_benchmark_path, "lbf_regression_model_300w_68_landmarks.txt"), method="lbf")

In [12]:
local_trees_68_landmarks_test_error = compute300WError(local_trees_alignment, bounding_boxes, images, ground_truth)
test_errors.append(local_trees_68_landmarks_test_error)
labels.append("Local trees regression - fullset")

lbf_68_landmarks_test_error = compute300WError(lbf_alignment, bounding_boxes, images, ground_truth)
test_errors.append(lbf_68_landmarks_test_error)
labels.append("Global regression - fullset")

print "Local trees regression mean test error: %0.2f%%" % (np.mean(local_trees_68_landmarks_test_error)*100)
print "LBF regression mean test error: %0.2f%%" % (np.mean(lbf_68_landmarks_test_error)*100)

print "Local trees regression 10%%: %0.2f%%" % (np.percentile(sorted(local_trees_68_landmarks_test_error), 10) * 100)
print "Local trees regression 10%%: %0.2f%%" % (np.sum(np.asarray(local_trees_68_landmarks_test_error) < 0.1) / float(len(local_trees_68_landmarks_test_error)) * 100)
print "LBF regression 10%%: %0.2f%%" % (np.sum(np.asarray(lbf_68_landmarks_test_error) < 0.1) / float(len(lbf_68_landmarks_test_error))*100)


Local trees regression mean test error: 12.45%
LBF regression mean test error: 6.85%
Local trees regression 10%: 5.13%
Local trees regression 10%: 53.99%
LBF regression 10%: 87.81%

In [15]:
images, ground_truth, bounding_boxes = _300w.loadTestSet("common")
print "Size of testing set: %d"%images.shape[0]


Size of testing set: 554

In [17]:
local_trees_51_landmarks_test_error = compute300WError(local_trees_alignment, bounding_boxes, images, ground_truth)
test_errors.append(local_trees_51_landmarks_test_error)
labels.append("Local trees regression - common subset")

lbf_51_landmarks_test_error = compute300WError(lbf_alignment, bounding_boxes, images, ground_truth)
test_errors.append(lbf_51_landmarks_test_error)
labels.append("Global regression - common subset")

print "Local trees regression mean test error: %0.2f%%" % (np.mean(local_trees_51_landmarks_test_error)*100)
print "LBF regression mean test error: %0.2f%%" % (np.mean(lbf_51_landmarks_test_error)*100)

print "Local trees regression 10%%: %0.2f%%" % (np.sum(np.asarray(local_trees_51_landmarks_test_error) < 0.1) / float(len(local_trees_51_landmarks_test_error)) * 100)
print "LBF regression 10%%: %0.2f%%" % (np.sum(np.asarray(lbf_51_landmarks_test_error) < 0.1) / float(len(lbf_51_landmarks_test_error))*100)


Local trees regression mean test error: 9.75%
LBF regression mean test error: 5.40%
Local trees regression 10%: 65.52%
LBF regression 10%: 95.31%

In [ ]:
line_styles = ["r-", "g-", "r--", "g--"]

for error, line_style, label in zip(test_errors, line_styles, labels):
    ecdf(error, line_style, label=label)

xlabel("Error value")
ylabel("Error cumulative distribution")
legend(loc=4)

In [33]:
local_trees_landmarks_errors = computeErrorForAllLandmarks(local_trees_alignment, bounding_boxes, images, ground_truth, (36, 45), 68)
lbf_landmarks_errors = computeErrorForAllLandmarks(lbf_alignment, bounding_boxes, images, ground_truth, (36, 45), 68)

prev_figsize = pylab.rcParams['figure.figsize']
pylab.rcParams['figure.figsize'] = (16, 8)

subplot(211)
boxplot([local_trees_landmarks_errors[:,i] for i in range(local_trees_landmarks_errors.shape[1])], sym="")
subplot(212)
boxplot([lbf_landmarks_errors[:,i] for i in range(lbf_landmarks_errors.shape[1])], sym="")

pylab.rcParams['figure.figsize'] = prev_figsize



In [15]:
import cv2
from tools import *

faces = bounding_boxes[:28]
imgs = [np.copy(img) for img in images[:28]]

for face, img in zip(faces, imgs):
    shape = lbf_alignment.align(face, img)
    cv2.rectangle(img, tuple(np.asarray(face[:2]).astype(np.int)), tuple(np.asarray(face[2:]).astype(np.int)), (0,0,0), int(0.01*img.shape[0]))

    for landmark in shape:
        cv2.circle(img, tuple(landmark.astype(np.int)), int(0.01*img.shape[0]), (255,255,255), -1)

showMosaic(imgs, ncols=4)



In [16]:
indexes = [np.where((np.asarray(lbf_test_error) == sorted(lbf_test_error)[-(i+1)]))[0][0]for i in range(24)]

faces = bounding_boxes[indexes]
imgs = [np.copy(img) for img in images[indexes]]

for face, img in zip(faces, imgs):
    shape = lbf_alignment.align(face, img)
    cv2.rectangle(img, tuple(np.asarray(face[:2]).astype(np.int)), tuple(np.asarray(face[2:]).astype(np.int)), (0,0,0), int(0.01*img.shape[0]))

    for landmark in shape:
        cv2.circle(img, tuple(landmark.astype(np.int)), int(0.01*img.shape[0]), (255,255,255), -1)
        
showMosaic(imgs, ncols=4)


51 landmarks


In [17]:
images, ground_truth, bounding_boxes = _300w.loadTestSet(contour_landmarks = False)

def compute300WError(alignment_method, bounding_boxes, images, ground_truth):
    return computeError(alignment_method, bounding_boxes, images, ground_truth, (19, 28), 51)

test_errors = []

print "Size of testing set: %d"%images.shape[0]


Size of testing set: 689

In [18]:
local_trees_alignment = AlignmentMethod(os.path.join(config._300w_benchmark_path, "local_trees_regression_model_300w_51_landmarks.txt"))
lbf_alignment = AlignmentMethod(os.path.join(config._300w_benchmark_path, "lbf_regression_model_300w_51_landmarks.txt"), method="lbf")

In [19]:
local_trees_51_landmarks_test_error = compute300WError(local_trees_alignment, bounding_boxes, images, ground_truth)
test_errors.append(local_trees_51_landmarks_test_error)

lbf_51_landmarks_test_error = compute300WError(lbf_alignment, bounding_boxes, images, ground_truth)
test_errors.append(lbf_51_landmarks_test_error)

subplot(121)
hist(local_trees_51_landmarks_test_error)
subplot(122)
hist(lbf_51_landmarks_test_error)

print "Local trees regression test error: %0.2f%%" % (np.mean(local_trees_51_landmarks_test_error)*100)
print "LBF regression test error: %0.2f%%" % (np.mean(lbf_51_landmarks_test_error)*100)


Local trees regression test error: 12.37%
LBF regression test error: 5.90%

In [21]:
images, ground_truth, bounding_boxes = _300w.loadTestSet("common", contour_landmarks = False)

In [22]:
local_trees_test_error = compute300WError(local_trees_alignment, bounding_boxes, images, ground_truth)
test_errors.append(local_trees_test_error)

lbf_test_error = compute300WError(lbf_alignment, bounding_boxes, images, ground_truth)
test_errors.append(lbf_test_error)

subplot(121)
hist(local_trees_test_error)
subplot(122)
hist(lbf_test_error)

print "Local trees regression test error: %0.2f%%" % (np.mean(local_trees_test_error)*100)
print "LBF regression test error: %0.2f%%" % (np.mean(lbf_test_error)*100)


Local trees regression test error: 9.41%
LBF regression test error: 4.37%

In [25]:
test_errors = [local_trees_68_landmarks_test_error, lbf_68_landmarks_test_error, local_trees_51_landmarks_test_error, lbf_51_landmarks_test_error]
line_styles = ["r-", "g-", "r--", "g--"]
labels = ["Local tree regression - 68 landmarks", "Global regression - 68 landmarks", "Local tree regression - 51 landmarks", "Global regression - 51 landmarks"]

for error, line_style, label in zip(test_errors, line_styles, labels):
    ecdf(sorted(error)[:-5], line_style, label)

xlabel("Error value")
ylabel("Error cumulative distribution")
legend(loc=4)
savefig("test.eps", bbox_inches="tight")



In [28]:
local_trees_landmarks_errors = computeErrorForAllLandmarks(local_trees_alignment, bounding_boxes, images, ground_truth, (19, 28), 51)
lbf_landmarks_errors = computeErrorForAllLandmarks(lbf_alignment, bounding_boxes, images, ground_truth, (19, 28), 51)

prev_figsize = pylab.rcParams['figure.figsize']
pylab.rcParams['figure.figsize'] = (16,8)

subplot(211)
boxplot([local_trees_landmarks_errors[:,i] for i in range(local_trees_landmarks_errors.shape[1])], sym="", positions=range(18,69))
subplot(212)
boxplot([lbf_landmarks_errors[:,i] for i in range(lbf_landmarks_errors.shape[1])], sym="", positions=range(18,69))
_ = yticks((np.arange(0, 0.35, 0.05)))

pylab.rcParams['figure.figsize'] = prev_figsize


Timings


In [10]:
images, _, bounding_boxes = _300w.loadTestSet()

local_trees_alignment = AlignmentMethod(os.path.join(config.base_path, "models_bak", "alignment", "local_trees_regression_model_300w_opencv_detector.txt"))
#lbf_alignment = AlignmentMethod(os.path.join(config.models_path, "alignment", "lbf_regression_model_68_landmarks_opencv_detector.txt"), method="lbf")
lbf_alignment = AlignmentMethod(os.path.join(config.models_path, "alignment", "lbf_regression_model_68_landmarks_opencv_detector.txt"), method="lbf")

%timeit local_trees_alignment.align(bounding_boxes[0], images[0])
%timeit lbf_alignment.align(bounding_boxes[0], images[0])


1000 loops, best of 3: 690 µs per loop
1000 loops, best of 3: 865 µs per loop

In [11]:
images, _, bounding_boxes = _300w.loadTestSet(contour_landmarks=False)

local_trees_alignment = AlignmentMethod(os.path.join(config.base_path, "models_bak", "alignment", "local_trees_regression_model_300w_opencv_detector.txt"))
#lbf_alignment = AlignmentMethod(os.path.join(config.models_path, "alignment", "lbf_regression_model_68_landmarks_opencv_detector.txt"), method="lbf")
lbf_alignment = AlignmentMethod(os.path.join(config.models_path, "alignment", "lbf_regression_model_51_landmarks_opencv_detector.txt"), method="lbf")

%timeit local_trees_alignment.align(bounding_boxes[0], images[0])
%timeit lbf_alignment.align(bounding_boxes[0], images[0])


1000 loops, best of 3: 687 µs per loop
1000 loops, best of 3: 536 µs per loop

In [ ]: